<template>
    <div class="menu-management">
        <!-- 标题区域 -->
        <div class="box">
            <div class="size-24">菜单管理</div>
        </div>

        <!-- 搜索与新增按钮区域 -->
        <div class="search-bar">
            <div class="search-group flex gap-4 items-center">
                <!-- 菜单名称搜索 -->
                <el-input v-model="searchName" clearable style="width: 250px;" placeholder="请输入菜单名称"
                    :suffix-icon="Search" @change="handleSearch" />
                <!-- 菜单类型筛选 -->
                <el-select v-model="selectedType" clearable placeholder="请选择菜单类型" style="width: 250px;"
                    @change="handleSearch">
                    <el-option label="菜单" value="1" />
                    <el-option label="功能" value="2" />
                </el-select>
            </div>
            <!-- 新增按钮：点击打开表单弹窗 -->
            <el-button type="primary" @click="openAddForm">新增</el-button>
        </div>

        <!-- 菜单列表表格 -->
        <div class="menu-table">
            <el-table :data="currentPageData" style="width: 100%; margin-top: 20px;" row-key="id" border stripe
                default-expand-all :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
                <el-table-column prop="id" label="序号" width="100" align="center" />
                <el-table-column prop="title" label="页面标题" align="center" />
                <el-table-column prop="path" label="路径" align="center" />
                <el-table-column label="图标" align="center">
                    <template #default="scope">
                        <span v-if="scope.row.icon" class="icon-wrapper">
                            {{ scope.row.icon }}
                        </span>
                        <span v-else>-</span>
                    </template>
                </el-table-column>
                <el-table-column label="类型" align="center">
                    <template #default="scope">
                        {{ scope.row.type === 1 ? '菜单' : '功能' }}
                    </template>
                </el-table-column>
                <el-table-column prop="sort" label="排序" align="center" />
                <el-table-column label="操作" align="center">
                    <template #default="scope">
                        <el-button size="small" type="primary" @click="openEditForm(scope.row)">
                            编辑
                        </el-button>
                        <el-button size="small" type="danger" @click="handleDeleteMenu(scope.row.id)">
                            删除
                        </el-button>
                    </template>
                </el-table-column>
            </el-table>
        </div>

        <!-- 分页 -->
        <div class="demo-pagination-block">
            <el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[5, 10, 20, 50]"
                layout="total, sizes, prev, pager, next, jumper" :total="filteredTotal" :background="background"
                @size-change="handleSizeChange" @current-change="handleCurrentChange" />
        </div>

        <!-- 新增/编辑表单弹窗：默认隐藏，点击“新增”或“编辑”按钮显示 -->
        <el-dialog :title="isEditMode ? '编辑菜单' : '新增菜单'" v-model="isFormShow" width="600px" @close="closeForm">
            <el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px">
                <!-- 上级菜单 -->
                <el-form-item label="上级菜单" prop="pid">
                    <el-select v-model="formData.pid" placeholder="请选择上级菜单" style="width: 100%;">
                        <el-option label="顶级菜单" value="0" />
                        <el-option v-for="item in menuTableData" :key="item.id" :label="item.title"
                            :value="item.id.toString()" />
                    </el-select>
                </el-form-item>
                <!-- 菜单标题 -->
                <el-form-item label="菜单标题" prop="title">
                    <el-input v-model="formData.title" placeholder="请输入菜单标题" style="width: 100%;" />
                </el-form-item>
                <!-- 菜单路径 -->
                <el-form-item label="菜单路径" prop="path">
                    <el-input v-model="formData.path" placeholder="请输入菜单路径" style="width: 100%;" />
                </el-form-item>
                <!-- 菜单图标 -->
                <el-form-item label="菜单图标" prop="icon">
                    <el-input v-model="formData.icon" placeholder="请输入菜单图标" style="width: 100%;" />
                </el-form-item>
                <!-- 是否菜单 -->
                <el-form-item label="是否菜单" prop="type">
                    <el-radio-group v-model="formData.type">
                        <el-radio label="1">菜单</el-radio>
                        <el-radio label="2">功能</el-radio>
                    </el-radio-group>
                </el-form-item>
                <!-- 菜单排序 -->
                <el-form-item label="菜单排序" prop="sort">
                    <el-input v-model.number="formData.sort" type="number" placeholder="请输入排序序号" style="width: 100%;" />
                </el-form-item>
            </el-form>
            <template #footer>
                <el-button @click="closeForm">取消</el-button>
                <el-button type="primary" @click="submitForm">确认</el-button>
            </template>
        </el-dialog>
    </div>
</template>

<script setup lang="ts">
import { ref, onMounted, computed, reactive } from 'vue';
import { Search } from '@element-plus/icons-vue';
import type { FormInstance, FormRules } from 'element-plus';
import { ElMessage } from 'element-plus';
// 引入接口（需确保路径正确）
import { menuAdd, menuDelete, menuList } from '/@/api/permissions/menus';

// ---------------------- 表格与分页相关 ----------------------
const currentPage = ref(1);
const pageSize = ref(10);
const total = ref(0);
const filteredTotal = ref(0);
const searchName = ref('');
const selectedType = ref('');
const background = ref(true);

// 接口数据类型（扁平结构）
interface ApiMenuItem {
    id: number;
    pid: number;
    icon: string;
    path: string;
    title: string;
    type: number;
    sort: number;
    show: number;
    createtime: string;
    children?: ApiMenuItem[]; // 分级后新增的子级字段
}

// 表格数据类型（树形结构）
interface TableMenuItem extends ApiMenuItem {
    hasChildren?: boolean; // 表格树所需的“是否有子级”标识
}

const menuTableData = ref<TableMenuItem[]>([]);
const filteredMenuData = ref<TableMenuItem[]>([]);

// 初始化表格数据：从接口获取并分级
onMounted(() => {
    getMenuList();
});

/**
 * 递归函数：将扁平数组转换为树形结构
 * @param flatData - 接口返回的扁平菜单数据
 * @param parentId - 父级ID（默认0，顶级菜单）
 * @returns 分级后的树形结构数组
 */
const convertToTree = (flatData: ApiMenuItem[], parentId: number = 0): TableMenuItem[] => {
    // 1. 筛选当前父级的子菜单
    const children = flatData
        .filter(item => item.pid === parentId)
        .map(item => {
            // 2. 递归获取当前子菜单的子级（深度遍历）
            const childItems = convertToTree(flatData, item.id);
            // 3. 给当前菜单添加children和hasChildren字段
            return {
                ...item,
                children: childItems.length > 0 ? childItems : undefined, // 无子级时不保留children字段
                hasChildren: childItems.length > 0, // 表格树需要的“是否有子级”标识
            } as TableMenuItem;
        })
        // 4. 按sort字段排序（保持菜单顺序）
        .sort((a, b) => a.sort - b.sort);

    return children;
};

// 获取菜单列表：调用接口 + 数据分级
const getMenuList = async () => {
    try {
        // 调用接口（传递搜索参数，如标题为空时查全部）
        const response = await menuList({ title: searchName.value || '' });

        if (response.code === 1) {
            // 1. 接口返回的扁平数据（假设response.data是扁平数组）
            const flatMenuData = response.data as ApiMenuItem[];
            console.log('接口返回的扁平数据:', flatMenuData);

            // 2. 调用递归函数，将扁平数据转换为树形结构（顶级菜单pid=0）
            const treeMenuData = convertToTree(flatMenuData, 0);
            console.log('分级后的树形数据:', treeMenuData);

            // 3. 更新表格数据和分页信息
            menuTableData.value = treeMenuData;
            filteredMenuData.value = [...treeMenuData];
            total.value = treeMenuData.length;
            filteredTotal.value = treeMenuData.length;
        } else {
            console.error('获取菜单列表失败，原因：', response.message);
        }
    } catch (error) {
        console.error('调用菜单列表接口失败：', error);
    }
};

// 搜索方法：筛选树形数据（支持子菜单筛选）
const handleSearch = () => {
    // 递归筛选树形数据（包含子菜单的匹配）
    const filterTree = (treeData: TableMenuItem[]): TableMenuItem[] => {
        return treeData
            .map(item => {
                // 先筛选当前节点的子菜单
                const filteredChildren = item.children ? filterTree(item.children) : [];
                // 匹配规则：当前节点标题包含搜索词，或子菜单有匹配项
                const isMatch =
                    item.title.includes(searchName.value) &&
                    (selectedType.value ? item.type === parseInt(selectedType.value) : true);

                // 保留“当前节点匹配”或“子菜单有匹配”的节点
                if (isMatch || filteredChildren.length > 0) {
                    return {
                        ...item,
                        children: filteredChildren.length > 0 ? filteredChildren : undefined,
                        hasChildren: filteredChildren.length > 0,
                    };
                }
                return null;
            })
            .filter(Boolean) as TableMenuItem[]; // 过滤掉null值
    };

    // 执行筛选并更新数据
    filteredMenuData.value = filterTree([...menuTableData.value]);
    filteredTotal.value = filteredMenuData.value.length;
    currentPage.value = 1; // 重置到第一页
};

// 当前页数据（分页处理树形结构）
const currentPageData = computed(() => {
    const start = (currentPage.value - 1) * pageSize.value;
    const end = start + pageSize.value;
    return filteredMenuData.value.slice(start, end);
});

// 分页事件
const handleSizeChange = (val: number) => {
    pageSize.value = val;
    currentPage.value = 1;
};
const handleCurrentChange = (val: number) => {
    currentPage.value = val;
};

// 删除方法（支持树形结构删除，需调用接口）
const handleDeleteMenu = async (id: number) => {    
    try {
        // 1. 调用删除接口
        const response = await menuDelete({ id });
        if (response.code === 1) {
            // 2. 重新获取分级后的列表（确保数据同步）
            await getMenuList();
            ElMessage.success('删除成功');
        } else {
            console.error('删除菜单失败，原因：', response.message);
        }
    } catch (error) {
        console.error('调用删除接口失败：', error);
    }
};

// ---------------------- 新增/编辑表单相关 ----------------------
const isFormShow = ref(false); // 表单弹窗显示状态（新增/编辑共用）
const isEditMode = ref(false); // 标识：true=编辑模式，false=新增模式
const currentEditId = ref<number | null>(null); // 当前编辑的菜单ID
const formRef = ref<FormInstance>(); // 表单实例（新增/编辑共用）

// 表单数据（新增/编辑共用）
const formData = reactive({
    title: '',       // 菜单标题
    path: '',        // 菜单路径
    icon: '',        // 菜单图标
    type: '1',       // 类型（1=菜单，2=功能）
    sort: 0,         // 排序（数字越小越靠前）
    pid: ''          // 父菜单ID（空表示顶级菜单，提交时转0）
});

// 表单验证规则（新增/编辑共用）
const formRules = reactive<FormRules<typeof formData>>({
    pid: [
        { required: true, message: '请选择上级菜单', trigger: 'change' }
    ],
    title: [
        { required: true, message: '请输入菜单标题', trigger: 'blur' },
        { min: 1, max: 20, message: '标题长度需在1-20字符之间', trigger: 'blur' }
    ],
    path: [
        { required: true, message: '请输入菜单路径', trigger: 'blur' },
        { pattern: /^\/[\w-\/]*$/, message: '路径需以“/”开头，仅允许字母、数字、“-”和“/”', trigger: 'blur' }
    ],
    icon: [
        { required: true, message: '请输入菜单图标', trigger: 'blur' }
    ],
    type: [
        { required: true, message: '请选择是否为菜单', trigger: 'change' }
    ],
    sort: [
        { required: true, message: '请输入排序序号', trigger: 'blur' },
        { type: 'number', message: '排序需为数字', trigger: 'blur' }
    ]
});

// 打开新增弹窗
const openAddForm = () => {
    isEditMode.value = false;
    currentEditId.value = null;
    // 重置表单
    if (formRef.value) {
        formRef.value.resetFields();
    }
    isFormShow.value = true;
};

// 打开编辑弹窗并回显数据
const openEditForm = (row: TableMenuItem) => {
    isEditMode.value = true;
    currentEditId.value = row.id;
    // 回显数据到表单
    formData.title = row.title;
    formData.path = row.path;
    formData.icon = row.icon;
    formData.type = row.type.toString();
    formData.sort = row.sort;
    formData.pid = row.pid.toString();
    isFormShow.value = true;
};

// 关闭弹窗
const closeForm = () => {
    isFormShow.value = false;
    // 重置表单
    if (formRef.value) {
        formRef.value.resetFields();
    }
    currentEditId.value = null;
    isEditMode.value = false;
};

// 提交表单（新增/编辑共用）
const submitForm = async () => {
    if (!formRef.value) return;

    await formRef.value.validate(async (valid, fields) => {
        if (valid) {
            try {
                // 构造接口所需参数
                const requestData: any = {
                    pid: formData.pid ? parseInt(formData.pid) : 0,
                    title: formData.title,
                    path: formData.path,
                    icon: formData.icon,
                    type: parseInt(formData.type),
                    sort: formData.sort
                };
                // 编辑时添加id
                if (isEditMode.value && currentEditId.value !== null) {
                    requestData.id = currentEditId.value;
                }

                // 调用接口
                const response = await menuAdd(requestData);
                if (response.code === 1) {
                    // 操作成功后重新获取分级列表
                    await getMenuList();
                    // 关闭弹窗并重置表单
                    closeForm();
                    ElMessage.success(isEditMode.value ? '编辑成功' : '新增成功');
                } else {
                    // 接口返回错误时提示
                    ElMessage.error(`${isEditMode.value ? '编辑' : '新增'}失败：${response.message || '未知错误'}`);
                    console.error(`${isEditMode.value ? '编辑' : '新增'}菜单接口返回错误`, response);
                }
            } catch (error) {
                // 接口请求异常时提示
                ElMessage.error(`${isEditMode.value ? '编辑' : '新增'}接口调用失败，请检查网络或接口配置`);
                console.error(`${isEditMode.value ? '编辑' : '新增'}菜单接口调用异常`, error);
            }
        } else {
            // 表单验证失败时提示（可选，增强用户体验）
            ElMessage.warning('表单验证失败，请检查必填项或格式是否正确');
            console.log('表单验证失败字段:', fields);
        }
    });
};
</script>
<style scoped>
.menu-management {
    padding: 20px;
}

.box {
    padding-left: 10px;
}

.size-24 {
    font-size: 24px;
    font-weight: 600;
    color: #1f2937;
    margin-bottom: 20px;
}

.search-bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
}

.gap-4 {
    gap: 16px;
}

.flex {
    display: flex;
}

.items-center {
    align-items: center;
}

.menu-table {
    background-color: #fff;
    border-radius: 8px;
}

.icon-wrapper {
    font-size: 14px;
}

.demo-pagination-block {
    width: 100%;
    margin-top: 20px;
    display: flex;
    justify-content: center;
}
.el-button--small {
    --el-button-size: 35px;
    height: var(--el-button-size);
}
</style>